package com.unionpay.service.common.excel;

import com.rpcservice.common.Log;
import com.unionpay.constant.SysConfig;
import com.unionpay.service.common.DateUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.*;

/**
 * @ClassName Excel
 * @Description: excel实体
 * @Author xsl
 * @Date 2021/1/14
 */
public class Excel {

    /**
     * excel工作簿
     */
    private Workbook workbook;

    /**
     * excel文件名称
     */
    private String excelName;

    /**
     * excel写入到多少行
     */
    private int lastRowNum;

    /**
     * excel文件位置与数据字段对应关系
     */
    private ExcelMapper excelMapper;

    /**
     * excel文件状态
     */
    private boolean isOpen = true;

    private Excel() {

    }


    /**
     * 获取excel实体
     *
     * @param template
     * @param headerCount
     * @return
     */
    public static Excel getExcel(String template, String fileName, final int headerCount, final ExcelMapper mapper) {
        Workbook workbook = getWorkbook(template, headerCount);
        return Excel.build(workbook, fileName, headerCount, mapper);
    }


    /**
     * 将数据写入excel
     *
     * @param dataList 数据集合
     * @return 处理行数，异常返回 -1
     */
    public int writeExcel(List<Map<String, Object>> dataList) {
        if (!isOpen) {
            throw new RuntimeException("该文件已被关闭！");
        }
        Sheet sheet = workbook.getSheetAt(0);
        if (Objects.isNull(sheet)) {
            return -1;
        }
        Set<ExcelField> mapper = excelMapper.getMapper();
        int handleRow = 0;
        for (Map<String, Object> data : dataList) {
            Row row = sheet.createRow(lastRowNum++);
            for (ExcelField excelField : mapper) {
                Cell cell = row.createCell(excelField.getIndex());
                String fieldName = excelField.getFieldName();
                if (Objects.equals("", fieldName)) {
                    continue;
                }
                Object value = data.get(fieldName);
                FieldHandle handle = excelField.getHandle();
                if (null != handle) {
                    value = handle.operation(value);
                }
                if (null == value) {
                    cell.setCellValue("");
                }
                if (value instanceof Integer) {
                    cell.setCellValue((Integer) value);
                } else if (value instanceof Long) {
                    cell.setCellValue((Long) value);
                } else if (value instanceof Double) {
                    cell.setCellValue((Double) value);
                } else {
                    cell.setCellValue(String.valueOf(value));
                }
            }
            handleRow++;
        }
        return handleRow;
    }

    /**
     * 输出到对应的流中
     *
     * @param out
     */
    public void writeStream(OutputStream out) {
        if (Objects.nonNull(workbook)) {
            try {
                workbook.write(out);
            } catch (IOException e) {
                Log.error(e.getMessage());
            }
        }
    }

    /**
     * 文件的绝对路径
     *
     * @return
     */
    public String writeFile() {
        long dayStart = DateUtils.getDayStart();
        File path = new File(SysConfig.EXCEL_EXPORT_FILE_PATH + File.separator + dayStart);
        if (!path.exists()) {
            if (!path.mkdirs()) {
                Log.error("文件夹创建失败：" + path.getAbsolutePath());
                return "";
            }
        }
        File file = new File(path, excelName + ".xlsx");
        if (!file.exists()) {
            try {
                boolean newFile = file.createNewFile();
            } catch (IOException e) {
                Log.error(e.getMessage());
            }

        }
        try (FileOutputStream outputStream = new FileOutputStream(file)) {
            workbook.write(outputStream);
        } catch (IOException e) {
            Log.error(e.getMessage());
            return "";
        }
        return file.getAbsolutePath();
    }


    public void close() {
        try {
            if (Objects.nonNull(workbook)) {
                workbook.close();
                isOpen = false;
            }
        } catch (IOException e) {
            Log.error(e.getMessage());
        }
    }


    private static Excel build(Workbook workbook, String fileName, int headerCount, ExcelMapper mapper) {
        Excel excel = new Excel();
        excel.workbook = workbook;
        excel.lastRowNum = headerCount;
        excel.excelName = fileName;
        excel.excelMapper = mapper;
        return excel;
    }

    private static Workbook getWorkbook(String template, final int headerCount) {
        File file = new File(SysConfig.EXCEL_TEMPLATES_PATH + template);
        try {
            return createWorkBook(file, headerCount);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static SXSSFWorkbook createWorkBook(File template, final int headerCount) throws Exception {
        FileInputStream is = new FileInputStream(template);
        XSSFWorkbook wb = new XSSFWorkbook(is);
        // 0
        int lastRowNum = wb.getSheetAt(0).getLastRowNum();
        if (lastRowNum < headerCount) {
            return new SXSSFWorkbook(wb, 1000);
        }
        Sheet sheet0 = wb.getSheetAt(0);
        for (int i = lastRowNum; i >= headerCount; i--) {
            Row baseRow1 = sheet0.getRow(i);
            if (Objects.isNull(baseRow1)) {
                continue;
            }
            sheet0.removeRow(baseRow1);
        }
        return new SXSSFWorkbook(wb, 1000);
    }

}